Shadow Door User's Manual
Copyright 2003 by Robert Zubek and Phillip Saltzman, Northwestern University
shadow-door-dev@cs.northwestern.edu
Using Shadow Door
To use Shadow Door in an NWN module, the module need to be configured to
communicate through the socket, and then an external process needs to send
properly formatted commands into the socket, and retrieve observations.
Game Side: Setting up the NPC
Suppose you already have a game module with an NPC that you would like to be
controlled externally. We will need to set up the NPC to talk
through Shadow Door. Open your module in the Aurora Toolbox and:
-
Go to File | Import, select shadowdoor.erf
- this imports the script code
-
Go to Edit | Module Properties, then the Events
tab. Under OnModuleLoad select sd_on_load
-
Create a new creature or select an existing NPC, then open its Properties
dialog. Under the Scripts tab:
-
Set the OnConversation event to sd_on_conv
-
Set the OnHeartbeat event to sd_on_heartbeat
-
Set the OnPhysicalAttacked event to sd_on_attack
-
Set the OnSpawn event to sd_on_spawn
And that's all we need inside the module!
External Controller Side: Communication Through the Socket
Socket communication is accomplished using a very simple text protocol. Please
proceed to the Under the Hood chapter for all
the gory details...
Scripting Details
Code included in shadowdoor.erf is a collection of very simple scripts
that:
-
Retrieve commands from the socket interface, deserialize and perform them.
This happens in the sd_on_heartbeat script - do_things()
retrieves and deserializes the command, and an appropriate handler is called.
The handler then optionally retrieves additional data, and performs the action
of the command.
-
Observe events in the game, serialize appropriate observation strings and
send them over the socket.
This happens in sd_on_attack, and similar scripts. Once triggered, the
scripts assemble the observation and send it over.
In particular, functionality in the scripts is accomplished by four functions:
-
void SD_Init ()
Initializes the Shadow Door scripts
-
string SD_RequestMsg () => <result>
Result of "0" means no new messages are available, "-1" means
message processing is still pending (i.e. SD_ReleaseMsg () had not been called
yet), and any other value indicates success.
-
string SD_GetNextToken () => <token>
Returns the next token in the serialized command. The first token is, of
course, the command type, and subsequent tokens are the arguments. Returns an
empty string if the token is unspecified, or no more tokens are available.
-
void SD_ReleaseMsg ()
Indicates end of processing. To be called after all handlers finished
their jobs.
-
void SD_Send (string <message>)
Takes an already serialized observation string, and sends it through
the Shadow Door
Adding New Commands
Commands can be added by extending the sd_on_heartbeat script.
First, create a void handler function, akin to do_move(), do_animate(),
and so on. It should call SD_GetNextToken() repeatedly to retrieve
optional arguments, then perform the action and exit. Finally, add the handler
function to do_things().
Adding New Observations
Due to the event-driven nature of NWScript, there are limits on the kinds of
observations that can be performed. In the creature's Properties
window select the Scripts tab, then pick and edit the
appropriate entry.
A script file for an event should begin with the line:
#include "sd_include"
which includes the necessary Shadow Door functions. Subsequently, the main()
function should assemble the serialized observation string, and call SD_Send()
to ship it.
System Limitations / To Do List
This being the first release, the system has some limitations which we hope to
rectify soon:
-
The interface only supports one NPC.
-
Only a handful of commands and observations are implemented.
-
Connections are not authenticated; anyone can connect to an open interface
port.